/**
 * @description: 钉钉开放平台接口请求
 * @version: 0.0.1
 * @author: hxx
 * @Date: 2023-09-26 16:16:07
 */
import { Config } from '@midwayjs/decorator';
import { Provide, HttpClient } from '@midwayjs/core';

@Provide()
export class OapiDingtalk {

  @Config('dingtalkAuthConfig')
  dingtalkAuthConfig: any;

  /**
    * @description:根据unionid获取用户userid
    * 文档地址：https://open.dingtalk.com/document/isvapp-server/query-a-user-by-the-union-id
    * @param {string} unionid 员工在当前开发者企业账号范围内的唯一标识，系统生成，不会改变。
    * @param {string} token  调用服务端API的应用凭证。
    *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
    *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
    * @returns {string}
    */
  async getByUnionid(unionid: string, token: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/user/getbyunionid?access_token=${token}`;
      const _data = { "unionid": unionid };
      return await this.httpRequest("POST", _url, _data, {});
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-getByUnionid-系统错误", data: error };
    }
  }


  /**
   * 获取企业内部应用的access_token
   * 文档地址：https://open.dingtalk.com/document/orgapp-server/obtain-orgapp-token
   * @param {string} appKey 
   * @param {string} appSecret 
   * @returns 
   */
  async obtainOrgappToken(appKey: string, appSecret: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/gettoken?appkey=${appKey}&appsecret=${appSecret}`;
      return await this.httpRequest("GET", _url);
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-obtainOrgappToken-系统错误", data: error };
    }
  }


  /**
   * 查询用户详情
   * 文档地址：https://open.dingtalk.com/document/isvapp-server/query-user-details
   * @param {string} userid    用户的userId。
   * @param {string} token  调用服务端API的应用凭证。
   *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
   *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
   * @returns 
   */
  async queryUserDetails(userid: string, token: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/v2/user/get?access_token=${token}`;
      const _data = {
        "language": "zh_CN",
        "userid": userid
      }
      return await this.httpRequest("POST", _url, _data);
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-queryUserDetails-系统错误", data: error };
    }
  }


  /**
   * 获取部门列表
   * 文档地址：https://open.dingtalk.com/document/isvapp-server/obtain-the-department-list-v2
   * @param {number} dept_id    部门ID，如果是根部门，该参数传1。
   * @param {string} token  调用服务端API的应用凭证。
   *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
   *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
   * @returns 
   */
  async queryDepartmentList(dept_id: number, token: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/v2/department/listsub?access_token=${token}`;
      const _data = {
        "language": "zh_CN",
        "dept_id": dept_id
      }
      return await this.httpRequest("POST", _url, _data);
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-queryDepartmentList-系统错误", data: error };
    }
  }

  /**
   * 获取部门用户基础信息
   * 文档地址：https://open.dingtalk.com/document/isvapp-server/queries-the-simple-information-of-a-department-user
   * @param {number} dept_id    部门ID，如果是根部门，该参数传1。 
   * @param {string} token  调用服务端API的应用凭证。
   *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
   *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
   * @returns 
   */
  async queryUserListsimple(dept_id: number, token: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/user/listsimple?access_token=${token}`;
      const _data = {
        "contain_access_limit": false,  //  是否返回访问受限的员工
        "order_field": "modify_desc",   //  部门成员的排序规则
        "language": "zh_CN",            //  通讯录语言，取值
        "size": 90,             //  分页长度，最大值100。
        "cursor": 0,            //  分页查询的游标，最开始传0，后续传返回参数中的next_cursor值。
        "dept_id": dept_id
      }
      return await this.httpRequest("POST", _url, _data);
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-queryUserListsimple-系统错误", data: error };
    }
  }

  /**
   * 获取部门详情
   * 文档地址：https://open.dingtalk.com/document/orgapp-server/query-department-details0-v2
   * @param {number} dept_id    部门ID，如果是根部门，该参数传1。
   * @param {string} token  调用服务端API的应用凭证。
   *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
   *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
   * @returns 
   */
  async queryDepartmentDetails(dept_id: number, token: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/v2/department/get?access_token=${token}`;
      const _data = {
        "dept_id": dept_id,
        "language": "zh_CN"
      }
      return await this.httpRequest("POST", _url, _data);
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-queryDepartmentDetails-系统错误", data: error };
    }
  }

  /**
   * 获取在职员工列表
   * 文档地址：https://open.dingtalk.com/document/isvapp-server/intelligent-personnel-query-the-list-of-on-the-job-employees-of-the
   * @param {string} status_list    在职员工状态筛选，可以查询多个状态。不同状态之间使用英文逗号分隔。 2：试用期 3：正式 5：待离职 -1：无状态
   * @param {string} offset    分页游标，从0开始。根据返回结果里的next_cursor是否为空来判断是否还有下一页，且再次调用时offset设置成next_cursor的值。
   * @param {string} size    分页大小，最大50。
   * @param {string} token  调用服务端API的应用凭证。
   *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
   *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
   * @returns 
   */
  async queryOnJobUserLists(offset: any, token: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/smartwork/hrm/employee/queryonjob?access_token=${token}`;
      const _data = {
        "status_list": "2,3,5,-1",
        "size": "50",
        "offset": offset
      }
      return await this.httpRequest("POST", _url, _data);
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-queryOnJobUserLists-系统错误", data: error };
    }
  }

  /**
   * 获取子部门ID列表
   * 文档地址：https://open.dingtalk.com/document/isvapp-server/obtain-a-sub-department-id-list-v2
   * @param {string} dept_id    父部门ID，根部门传1
   * @param {string} token  调用服务端API的应用凭证。
   *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
   *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
   * @returns 
   */
  async queryDepartmentListsubid(dept_id: string, token: string) {
    try {
      const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/v2/department/listsubid?access_token=${token}`;
      const _data = {
        "dept_id": dept_id,
      }
      return await this.httpRequest("POST", _url, _data);
    } catch (error) {
      return { success: false, msg: "sdk-ddTopOapi-queryDepartmentListsubid-系统错误", data: error };
    }
  }

    /**
   * 查询用户详情
   * 文档地址：https://open.dingtalk.com/document/orgapp/query-user-details
   * @param {string} userid    userid
   * @param {string} token  调用服务端API的应用凭证。
   *                   1.企业内部应用，通过获取企业内部应用的access_token接口获取。
   *                   2.第三方企业应用，通过服务商获取第三方应用授权企业的access_token接口获取。
   * @returns 
   */
    async queryGetUserDeatils(userid: string, token: string) {
      try {
        const _url = `${this.dingtalkAuthConfig.oapi_uri}/topapi/v2/user/get?access_token=${token}`;
        const _data = {
          "userid": userid,
        }
        return await this.httpRequest("POST", _url, _data);
      } catch (error) {
        return { success: false, msg: "sdk-ddTopOapi-queryGetUserDeatils-系统错误", data: error };
      }
    }

  /**
     * 发起请求
     * @param {string} method 
     * @param {string} url 
     * @param {string} data 
     * @param {string} headers 
     * @returns 
     */
  async httpRequest(method: string, url: string, data: object = {}, headers: object = {}) {
    try {
      const httpclient = new HttpClient();
      const res = await httpclient.request(url, {
        method: method,
        data: data,
        dataType: 'json',
        contentType: 'json',   // 发送的 post 为 json
        headers: {
          'Content-Type': 'application/json',
          ...headers
        }
      });
      if (res && res.data && res.data.errcode == 0) {
        if (res.data.result) {
          return { success: true, ...res.data.result }
        }
        return { success: true, ...res.data }
      } else {
        return { success: false, ...res.data }
      };
    } catch (error) {
      throw error;
    }
  }
}